<?php


/*
 * This class applies a changes from a match to the teams  
 */

class MatchUpdater {

    function updateTeams(& $match, & $homeTeam, & $awayTeam) {
        $errors = array ();
        $this->updateTeam($errors, $homeTeam, $match->homeRec);
        $this->updateTeam($errors, $awayTeam, $match->awayRec);
        if (count($errors) == 0) {
            $homeTeam->save();
            $awayTeam->save();
            $match->teamsUpdated=true;
        }
        
        return $errors;
    }

    function updateTeam(& $errors, & $team, $matchRecord) {
        $team->fanFactor += $matchRecord->fanFactor;

        $team->treasury += ($matchRecord->winnings / 1000);

        // removes spiralling expenses
        $team->treasury = max(0, $team->treasury - $this->calcSpirallingExpenses($team->getTotalCost()));

        $cost = max(0, $team->race->rerollCost * 2 * $matchRecord->rerolls);
        if ($this->canBuy($team, $cost)) {
            $team->rerolls += $matchRecord->rerolls;
            $team->treasury -= $cost;
        } else {
            array_push($errors, "Insufficient funds to buy reroll, \$$team->treasury banked, but \$$cost needed");
        }

        $cost = max(0, 50 * $matchRecord->apothecary);
        if ($this->canBuy($team, $cost)) {
            $team->apothecary += $matchRecord->apothecary;
            $team->treasury -= $cost;
        } else {
            array_push($errors, "Insufficient funds to buy apothecary, \$$team->treasury banked, but \$$cost needed");
        }

        $cost = max(0, 10 * $matchRecord->cheerleaders);
        if ($this->canBuy($team, $cost)) {
            $team->cheerleaders += $matchRecord->cheerleaders;
            $team->treasury -= $cost;
        } else {
            array_push($errors, "Insufficient funds to buy cheerleaders, \$$team->treasury banked, but \$$cost needed");
        }

        $cost = max(0, 10 * $matchRecord->coaches);
        if ($this->canBuy($team, $cost)) {
            $team->coaches += $matchRecord->coaches;
            $team->treasury -= $cost;
        } else {
            array_push($errors, "Insufficient funds to buy coaches, \$$team->treasury banked, but \$$cost needed");
        }
		$pmrDao = new PlayerMatchRecordDao();
        $pmrs = $pmrDao->getPMRsForMatch($matchRecord);
        foreach ($pmrs as $pmr) {
            $this->updatePlayer($errors, $team, $pmr->player, $pmr);
            $team->setPlayer($pmr->player);
        }

        $this->purchases($errors, $team, $matchRecord->getPurchases());

    }

    /**
     * Must be done after player updates because of the interaction with deaths
     */
    function purchases(& $errors, & $team, $purchases) {
        foreach ($purchases as $purchase) {
            if ($this->canBuy($team, $purchase->cost)) {
                $originalPlayer = $team->getPlayer($purchase->rosterNum);
                if ($originalPlayer) {
                    /* Player exists on the team with the same roster number. Three options */
                    /* #1 Original player has died this game and this is a replacement */
                    if ($originalPlayer->cost == 0) {
                        $team->setPlayer($this->makePlayer($purchase));
                        $team->treasury-=$purchase->cost;
                    }
                    /* #2 Player is a journeyman who is being bought */
                    else if ($originalPlayer->isJourneyman()) {
                        $originalPlayer->position = $purchase->position->position;
                        if (0 == strcasecmp($originalPlayer->skills, "Loner")) {
                            $originalPlayer->skills = "";
                        } else {
                            $originalPlayer->skills = substr($originalPlayer->skills, 7);
                        }
                        $team->treasury-=$purchase->cost;
                    } else {
	                    /* #3 Error */
		                array_push($errors, "Player already exists for position $purchase->rosterNum");
                    }
                } else {
                    // Clear position just add
                    $team->setPlayer($this->makePlayer($purchase));
                    $team->treasury-=$purchase->cost;
                }
            } else {
                // Can't Afford player
                array_push($errors, "Insufficient funds to buy player, $purchase->name $purchase->position->position \$$team->treasury banked, but \$$purchase->cost needed");
            }
        }
    }

    function makePlayer($purchase) {
        $player = new Player();
        $player->name = $purchase->name;
        $player->rosterNum = $purchase->rosterNum;
        $player->position = $purchase->position->position;
        $player->ma = $purchase->position->ma;
        $player->st = $purchase->position->st;
        $player->ag = $purchase->position->ag;
        $player->av = $purchase->position->av;
        $player->cost = $purchase->position->cost;
        $player->skills = $purchase->position->skillsStr;
        return $player;
    }

    function canBuy($team, $cost) {
        return $cost <= $team->treasury;
    }

    function updatePlayer(& $errors, & $team, & $player, $pmr) {
        $player->completions += $pmr->comps;
        $player->casualties += $pmr->cas;
        $player->tds += $pmr->tds;
        $player->interceptions += $pmr->ints;
        $player->mvps += $pmr->mvps;
        $position = $team->race->getPosition($player->position);
        if ($pmr->hasSkill()) {
            $skill = $pmr->skill;
            $player->skills = $this->addSkill($player->skills, $skill->name);
            if (0 == strlen($skill->group)) {
            	// stat - add 30, then more for AG & ST
                $player->cost += 30;
            } else {
				$match = false;
				foreach($position->singleSkillGroups as $group) {
				    if (!strncasecmp($group, $skill->group, 1)) {
				        $match = true;
				    }
				}
				if ($match) {
				    $player->cost +=20;
				} else {
	                $player->cost += 30;
				}
            }
            switch ($skill->id) {
                // +MA
                case 75 :
                case 76 :
                    $player->ma = $this->changeStat($position->ma, $player->ma + 1);
                    break;
                    // +Av
                case 77 :
                case 78 :
                    $player->av = $this->changeStat($position->av, $player->av + 1);
                    break;
                    // +AG
                case 79 :
                case 80 :
                    $player->ag = $this->changeStat($position->ag, $player->ag + 1);
                	$player->cost += 10;
                    break;
                    // +ST
                case 81 :
                case 82 :
                    $player->st = $this->changeStat($position->st, $player->st + 1);
	                $player->cost += 20;
                    break;
                    // Everything else
                default :
                    break;
            }

        }
        // TODO - If you go below min stat you still show the "skill" change
        switch ($pmr->injury) {
            case "MNG" :
                $player->injured = true;
                break;
            case "Niggle" :
                $player->injured = true;
                $player->niggles++;
                break;
            case "-MA" :
                $player->injured = true;
                $player->ma = $this->changeStat($position->ma, $player->ma - 1);
                $player->skills = $this->addSkill($player->skills, "-MA");
                break;
            case "-Av" :
                $player->injured = true;
                $player->av = $this->changeStat($position->av, $player->av - 1);
                $player->skills = $this->addSkill($player->skills, "-Av");
                break;
            case "-AG" :
                $player->injured = true;
                $player->ag = $this->changeStat($position->ag, $player->ag - 1);
                $player->skills = $this->addSkill($player->skills, "-AG");
                break;
            case "-ST" :
                $player->injured = true;
                $player->st = $this->changeStat($position->st, $player->st - 1);
                $player->skills = $this->addSkill($player->skills, "-ST");
                break;
            case "Dead" :
                $player->injured = false;
                $player->cost = 0;
                break;
            default :
                $player->injured = false;
                break;
        }
    }

    function changeStat($positionValue, $newValue) {
        $min = max($positionValue -2, 1);
        $max = min($positionValue +2, 10);
        $newValue = max($newValue, $min);
        $newValue = min($newValue, $max);
        return $newValue;
    }

    function addSkill($start, $new) {
        if (strlen($start) == 0)
            return $new;
        return $start . ", " . $new;
    }

    /**
     * Calculates the given spirialling expenses based on current season config
     */
    function calcSpirallingExpenses($tv) {
    	global $season;
        $step = $season->spiralInc;
        $start = $season->spiralStart - 1;
        $expenses = 0;
        if ($tv > $start) {
            $excess = $tv - $start;
            $mod = $excess % $step;
            $excess = $excess + ($step - $mod);
            $multiplier = $excess / $step;
            $expenses = 10 * $multiplier;
        }
        logger("Spiralling Expenses for " . $tv . " are " . $expenses);
        return $expenses;
    }
}
?>
